The iOS new functionality for rendering to a PDF file means that anything you can draw to the screen using UIView
can now be drawn straight into a PDF file. Here, you'll learn how to do
so by "wrapping" your drawing code in a special PDF-generation context.
Generating a PDF is great, but you may ask, "What am I going to do with that PDF file?" We'll stick to technology that has been a part
of iOS ever since way back in version 3.0—sending an e-mail message with an attachment using MFMailComposeViewController.
We'll add this new
functionality to our Dudel app. First, in the header file for our
controller class, we'll need a new action method, to be triggered from
the GUI. We're also going to declare that our controller conforms to the
MFMailComposeViewControllerDelegate
protocol, so that we'll be notified when the user has composed and sent
the e-mail message or hit Cancel to discard it. We need to include the
relevant header for accessing the mail composition GUI. Here's the
updated version of DudelViewController.h, containing those changes:
// DudelViewController.h
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#import "Tool.h"
#import "DudelView.h"
@interface DudelViewController : UIViewController <ToolDelegate, DudelViewDelegate, MFMailComposeViewControllerDelegate> {
id <Tool> currentTool;
IBOutlet DudelView *dudelView;
IBOutlet UIBarButtonItem *freehandButton;
IBOutlet UIBarButtonItem *ellipseButton;
IBOutlet UIBarButtonItem *rectangleButton;
IBOutlet UIBarButtonItem *lineButton;
IBOutlet UIBarButtonItem *pencilButton;
UIColor *strokeColor;
UIColor *fillColor;
}
@property (retain, nonatomic) id <Tool> currentTool;
@property (retain, nonatomic) UIColor *strokeColor;
@property (retain, nonatomic) UIColor *fillColor;
- (IBAction)touchFreehandItem:(id)sender;
- (IBAction)touchEllipseItem:(id)sender;
- (IBAction)touchRectangleItem:(id)sender;
- (IBAction)touchLineItem:(id)sender;
- (IBAction)touchPencilItem:(id)sender;
- (IBAction)touchSendPdfEmailItem:(id)sender;
@end
Now go back to project navigation pane in Xcode, and look for the Frameworks section. Right-click it and select Add => Existing Frameworks... from the context menu, then double-click MessageUI.framework so that Dudel can make use of it.
Next, let's take care of what we need to hook up in Interface Builder. Open DudelViewController.xib,
and take a look at the toolbar at the bottom of the window. We want to
put a new item in the toolbar that will call our new method, but it
should be separated from the drawing tools, so we need some space there
as well.
Use the Library to search for
"bar button item," and you'll see all the sorts of things that you can
put into your toolbars. For this example, drag a Flexible Space Bar
Button Item out and place it in our toolbar, to the right of everything
else. You'll see it expand to fill all of the available space in the
toolbar. Then drag a Bar Button Item from the Library to the far-right
end of the toolbar. While it's still selected, use the attribute
inspector to make sure its Style is set to Bordered, and set its Title
to Email PDF. Then control-drag from the new item to File's Owner in the main .nib window, and select touchSendPdfEmailItem: from the context menu that appears. We're finished with Interface Builder for now, so save your work and go back to Xcode.
It's time to implement the code that will initiate the PDF rendering. Add the following method:
- (IBAction)touchSendPdfEmailItem:(id)sender {
// set up PDF rendering context
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData(pdfData, dudelView.bounds, nil);
UIGraphicsBeginPDFPage();
// tell our view to draw
[dudelView drawRect:dudelView.bounds];
// remove PDF rendering context
UIGraphicsEndPDFContext();
// send PDF data in mail message
MFMailComposeViewController *mailComposer = [[[MFMailComposeViewController alloc] init] autorelease];
mailComposer.mailComposeDelegate = self;
[mailComposer addAttachmentData:pdfData mimeType:@"application/pdf" fileName:@"Dudel creation.pdf"];
[self presentModalViewController:mailComposer animated:YES];
}
All we do here is set up a special context using an NSMutableData object to contain the PDF content, and call our view object's drawRect: method. When we're finished, we pass the PDF data off to the message-composing window.
We also need to implement
the following method, so that the e-mail composer can let us know that
the user has clicked either Send or Cancel in the window. It's our duty
to end the modal session here.
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
[self dismissModalViewControllerAnimated:YES];
}
Now you're all set! Build and
run, create something with the tools, and then hit the Email PDF
button. You'll see that the content of your view is a visible attachment
in a new e-mail window, ready for you to send to your admirers!